package org.example.util.video;

import org.example.util.log.Logac;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @auther admin闫
 * @Descriptopn 处理视频相关的工具类【必须安装FFmpeg】
 * @date 2024/4/8 20:29
 */
public class VideoMp4Util {


    public static String ffmpeg_path="d:\\windos软件安装根目录\\pythonpath\\ffmpeg--full_build\\ffmpeg-2023-06-08-git-024c30aa3b-full_build\\bin\\ffmpeg.exe";


    /**
     * 根据长度裁剪音频
     * @param specifiedDuration 音频长度
     * @param inputAudioPath 输入路径
     * @param outputAudioPath 输出；路径
     * @throws IOException
     * @throws InterruptedException
     */
    public static void cutAudio(double specifiedDuration, String inputAudioPath, String outputAudioPath) throws IOException, InterruptedException {
        String ffmpegCmd = "ffmpeg -i " + inputAudioPath + " -ss 0 -t " + specifiedDuration + " -c copy " + outputAudioPath;
        Process process = Runtime.getRuntime().exec(ffmpegCmd);
        process.waitFor();
    }

    /**
     * 合成mp4视频和mp3音频[覆盖音频]
     * @param videoFile 视频路径
     * @param audioFile 音频路径
     * @param outputFile 输出路径
     * @return   return outputFile; 合成成功   /  return "false"; 合成失败
     * [视频长度与音频长度不一致时，以视频长度作为输出的最后结果]
     *
     */
    public static String videoMp4AndMp3(String videoFile,String audioFile,String outputFile){
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(
                    "ffmpeg",
                    "-i", videoFile,
                    "-i", audioFile,
                    "-c:v", "copy",
                    "-c:a", "aac",
                    "-strict", "experimental",
                    "-map", "0:v:0",
                    "-map", "1:a:0",
                    "-shortest",
                    outputFile
            );
            processBuilder.redirectErrorStream(true);

            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("视频音频合并成功！");
                return outputFile;
            } else {
                Logac.log(exitCode+"---"+videoFile+"：视频音频合并失败！");
                return "false";
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return "false";
    }

    /**
     * 合成mp4视频和mp3音频，[叠加音频到视频上而不是替换原始音频]
     * @param videoFile 视频路径
     * @param audioFile 音频路径
     * @param outputFile 输出路径
     * @return   return outputFile; 合成成功   /  return "false"; 合成失败
     * [视频长度与音频长度不一致时，以视频长度作为输出的最后结果]
     *
     */
    public static String overlayAudioOnVideo(String videoFile, String audioFile, String outputFile) {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(
                    "ffmpeg",
                    "-i", videoFile,
                    "-i", audioFile,
                    "-filter_complex", "[0:a][1:a]amerge=inputs=2[a]", // 合并视频和音频流
                    "-map", "0:v", // 使用视频流来自第一个输入文件
                    "-map", "[a]", // 使用合并后的音频流
                    "-c:v", "copy", // 复制视频编解码器
                    "-c:a", "aac", // 使用AAC编码音频
                    "-strict", "experimental",
                    outputFile
            );
            processBuilder.redirectErrorStream(true);

            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("视频音频合并成功！");
                return outputFile;
            } else {
                Logac.log(exitCode+"---"+videoFile+"：视频音频合并失败！");
                return "false";
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return "false";
    }


    /**
     * 获取视频总时间
     * @param video_path    视频路径
     * @return
     */
    public static int getVideoTime(String video_path) {
        List<String> commands = new java.util.ArrayList<String>();
        commands.add(ffmpeg_path);
        commands.add("-i");
        commands.add(video_path);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commands);
            final Process p = builder.start();

            //从输入流中读取视频信息
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            StringBuffer sb = new StringBuffer();
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            br.close();

            //从视频信息中解析时长
            String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
            Pattern pattern = Pattern.compile(regexDuration);
            Matcher m = pattern.matcher(sb.toString());
            if (m.find()) {
                int time = getTimelen(m.group(1));
                System.out.println(video_path+",视频时长："+time+", 开始时间："+m.group(2)+",比特率："+m.group(3)+"kb/s");
                return time;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }

    //格式:"00:00:10.68"
    private static int getTimelen(String timelen){
        int min=0;
        String strs[] = timelen.split(":");
        if (strs[0].compareTo("0") > 0) {
            min+=Integer.valueOf(strs[0])*60*60;//秒
        }
        if(strs[1].compareTo("0")>0){
            min+=Integer.valueOf(strs[1])*60;
        }
        if(strs[2].compareTo("0")>0){
            min+=Math.round(Float.valueOf(strs[2]));
        }
        return min;
    }


    /**
     * 合成mp4视频和mp3音频，叠加音频到视频上并调整音量
     * @param videoFile 视频路径
     * @param audioFile 音频路径
     * @param outputFile 输出路径
     * @param volume 要调整的音频音量，范围为0.0到1.0
     * @return   return outputFile; 合成成功   /  return "false"; 合成失败
     * [视频长度与音频长度不一致时，以视频长度作为输出的最后结果]
     *
     */
    public static String overlayAudioOnVideoWithVolume(String videoFile, String audioFile, String outputFile, double volume) {
        try {
            String volumeFilter = "volume=" + volume;
            ProcessBuilder processBuilder = new ProcessBuilder(
                    "ffmpeg",
                    "-i", videoFile,
                    "-i", audioFile,
                    "-filter_complex", "[0:a][1:a]amerge=inputs=2[a];[a]" + volumeFilter + "[aout]", // 合并视频和音频流并调整音量
                    "-map", "0:v", // 使用视频流来自第一个输入文件
                    "-map", "[aout]", // 使用调整音量后的音频流
                    "-c:v", "copy", // 复制视频编解码器
                    "-c:a", "aac", // 使用AAC编码音频
                    "-strict", "experimental",
                    outputFile
            );
            processBuilder.redirectErrorStream(true);

            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("视频音频合并成功！");
                return outputFile;
            } else {
                Logac.log(exitCode+"---"+videoFile+"：视频音频合并失败！");
                return "false";
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return "false";
    }


    /**
     * 把图片转换为指定长度的视频
     * @param imagePath 图片路径
     * @param videoLengthInSeconds 视频长度（秒）
     * @param outputVideoPath 视频输出路径 mp4
     */
    public static void convertImagesToVideo(String imagePath, int videoLengthInSeconds, String outputVideoPath) {
        try {
            // 构建 FFmpeg 命令
            String ffmpegCommand = "ffmpeg -loop 1 -i " + imagePath + " -t " + videoLengthInSeconds + " -pix_fmt yuv420p " + outputVideoPath;
            // 执行 FFmpeg 命令
            Process process = Runtime.getRuntime().exec(ffmpegCommand);
            // 等待命令执行完毕
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("视频合成成功！");
            } else {
                Logac.log(exitCode+"---"+imagePath+"：视频音频合并失败！");
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
